﻿#pragma once
#include "Singleton.h"
#include "Buffer.h"
#include "Timer.h"
#include "ThreadLock.h"
#include "Atom.h"

namespace COMM
{
	// MT-safe in process.
	//
	class COMM_API Log : public Singleton<Log>
	{
	public:
		class COMM_API Logger
		{
		public:
			virtual ~Logger(){}
			virtual void Release(){ delete this; }
			virtual bool Open() = 0;
			virtual void Close() = 0;
			virtual bool Write(int level, const char* content, int size=-1) = 0;
		};

		class COMM_API SilenceLogger : public Logger
		{
		public:
			virtual bool Open();
			virtual void Close();
			virtual bool Write(int level, const char* content, int size=-1);
		};

		class COMM_API DefaultLogger : public Logger
		{
		public:
			DefaultLogger(const char* path=NULL, bool daily=true);
			~DefaultLogger();
			virtual bool Open();
			virtual void Close();
			virtual bool Write(int level, const char* content, int size=-1);
		protected:
			virtual bool WriteContent(const char* content, int size);
			String WrapContent(int level, const char* content, int size=-1);
		private:
			FILE* m_stream;
			bool m_daily;
			String m_path;
			CommTime m_filetime;
		};

		class COMM_API CachedLogger : public DefaultLogger
		{
		public:
			CachedLogger(const char* path=NULL, bool daily=true, size_t maxCapacity=-1, int intervalMs=100);
			~CachedLogger();
			virtual bool Write(int level, const char* content, int size=-1);
		private:
			static int PullProc(CommType& arg);
			int m_intervalMs;
			Thread* m_thread;
			AtomInt m_continue;
			MessageQueue m_queue;
		};

		class COMM_API StdoutLogger : public DefaultLogger
		{
		public:
			StdoutLogger(bool shortDate=true);
			virtual bool Open();
			virtual void Close();
		protected:
			virtual bool WriteContent(const char* content, int size);
		};

#ifdef COMM_MSVC
		class COMM_API WindowsLogger : public DefaultLogger
		{
		public:
			WindowsLogger(const char* appName);
			virtual bool Open();
			virtual void Close();
		protected:
			virtual bool WriteContent(const char* content, int size);
			HANDLE  m_hLog;
			String m_appName;
		};
#endif


		Log(void);
		~Log(void);
		void SetLogger(Logger* logger=NULL);
		Logger* GetLogger();
		// level: MYLIB_LOG_ERR - MYLIB_LOG_DEBUG.
		void SetLevel(int level);
		// log content max length: COMM_STRING_DEFAULT_LENGTH.
		bool Write(int level, const char* format, ...);
		bool VWrite(int level, const char* format, va_list args); 

	private:
		ThreadLock m_lock;
		Logger* m_logger;
		AtomInt m_level;
		
	};
}

